package com.star.cat.persitent.aspect;

import java.lang.reflect.Method;
import java.util.concurrent.ConcurrentHashMap;

import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.star.cat.common.parse.DefaultKeyParse;
import com.star.cat.common.parse.KeyParse;
import com.star.cat.persitent.annotation.PersistentClear;
import com.star.cat.persitent.service.PerService;

/**
 * PersistentClear注解拦截
 * 
 * @author liguangcai
 * @date 2018/08/28 17:38
 */
@Aspect
@Component
public class PersistentClearAspect {
	
	@Autowired
	private KeyParse keyParse;
	@Autowired
	private PerService perService;

	private ConcurrentHashMap<String, KeyParse> keyParseMap = new ConcurrentHashMap<>();

	/**
	 * 切点
	 */
	@Pointcut("@annotation(com.star.cat.persitent.annotation.PersistentClear)")
	public void pointCut() {
	}

	/**
	 * 增强处理 [1.userName#2.status]
	 * 
	 * @return
	 * @throws Throwable
	 */
	@Around("pointCut()&&@annotation(anno)")
	public Object around(ProceedingJoinPoint invocation, PersistentClear anno) throws Throwable {
		MethodSignature signature = (MethodSignature) invocation.getSignature();
		Method method = signature.getMethod();
		Class<?>[] paramClasses = method.getParameterTypes();
		Object[] params = invocation.getArgs();
		String realKey = "";
		if (StringUtils.isNotBlank(anno.key())) {
			realKey = getKey(anno, anno.key(), paramClasses, params);
			perService.delByKey(realKey);
		} else if (StringUtils.isNotBlank(anno.prefix())) {
			realKey = getKey(anno, anno.prefix(), paramClasses, params);
			perService.delByPrefix(realKey);
		} else if (StringUtils.isNotBlank(anno.fuzzy())) {
			realKey = getKey(anno, anno.fuzzy(), paramClasses, params);
			perService.delByFuzzy(realKey);
		} else if (anno.keys().length > 0) {
			for (String key : anno.keys()) {
				key = getKey(anno, key, paramClasses, params);
				perService.delByFuzzy(key);
			}
		}
		return invocation.proceed();
	}

	/**
	 * 解析Key表达式
	 * 
	 * @param anno
	 * @param key
	 * @param paramClasses
	 * @param params
	 * @return
	 * @throws InstantiationException
	 * @throws IllegalAccessException
	 */
	private String getKey(PersistentClear anno, String key, Class<?>[] paramClasses, Object[] params)
			throws InstantiationException, IllegalAccessException {
		String keyParseName = anno.keyParse().getName();
		KeyParse keyParse = null;
		if (anno.keyParse().equals(DefaultKeyParse.class)) {
			keyParse = this.keyParse;
		} else {
			if (keyParseMap.containsKey(keyParseName)) {
				keyParse = keyParseMap.get(keyParseName);
			} else {
				keyParse = anno.keyParse().newInstance();
				keyParseMap.put(keyParseName, keyParse);
			}
		}
		return keyParse.getKey(key, paramClasses, params);
	}

}
